package tools

import (
	"bytes"
	"fmt"
	"math/rand"
	"net/http"
	"peilian-api/app/global/log"
	"peilian-api/utils/format"
	"runtime"
	"strconv"
	"time"
	"unicode"

	"github.com/gin-gonic/gin"
)

func RecoverGoroutine() {
	if res := recover(); res != nil {
		if fmt.Sprint(res) != "send on closed channel" {
			fmt.Println("未知正常断开")
		}
		const size = 64 << 10
		buf := make([]byte, size)
		buf = buf[:runtime.Stack(buf, false)]
		log.Logger.Error(
			fmt.Sprintf("[协程%d]", GetGid()),
			"异常恢复, ",
			"异常内容: ", fmt.Sprint(res),
			" trace: ", string(buf),
		)
	}
}

func RecoverGoroutineCtx(ctx *gin.Context) {
	if res := recover(); res != nil {
		if fmt.Sprint(res) != "send on closed channel" {
			log.Logger.ErrorMsgF(ctx, fmt.Sprintf("异常：%s", fmt.Sprint(res)))
		}
		const size = 64 << 10
		buf := make([]byte, size)
		buf = buf[:runtime.Stack(buf, false)]
		log.Logger.ErrorF(ctx,
			fmt.Sprintf("[协程%d]", GetGid()),
			"异常恢复, ",
			"异常内容: ", fmt.Sprint(res),
			" trace: ", string(buf),
		)
	}
}

func GetGid() (gid uint64) {
	b := make([]byte, 64)
	b = b[:runtime.Stack(b, false)]
	b = bytes.TrimPrefix(b, []byte("goroutine "))
	b = b[:bytes.IndexByte(b, ' ')]
	n, err := strconv.ParseUint(string(b), 10, 64)
	if err != nil {
		panic(err)
	}
	return n
}

func RespOk(c *gin.Context, data interface{}) {
	c.JSON(http.StatusOK, &format.Res{
		Code: http.StatusOK,
		Data: data,
		Msg:  "成功",
	})
}

func Resp400(c *gin.Context, msg string) {
	c.JSON(http.StatusBadRequest, &format.Res{
		Code: http.StatusBadRequest,
		Data: make([]interface{}, 0),
		Msg:  msg,
	})
}

func GenerateRandomNumber(start int, end int, count int) []int {
	if end < start || (end-start) < count {
		return nil
	}
	nums := make([]int, 0)
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for len(nums) < count {
		num := r.Intn(end-start) + start
		exist := false
		for _, v := range nums {
			if v == num {
				exist = true
				break
			}
		}
		if !exist {
			nums = append(nums, num)
		}
	}
	return nums
}

func DiffArray(a []string, b []string) []string {
	var diffArray []string
	temp := map[string]struct{}{}

	for _, val := range b {
		if _, ok := temp[val]; !ok {
			temp[val] = struct{}{}
		}
	}

	for _, val := range a {
		if _, ok := temp[val]; !ok {
			diffArray = append(diffArray, val)
		}
	}

	return diffArray
}

func HanZiLen(s string) int64 {
	var count int64
	for _, v := range s {
		if unicode.Is(unicode.Han, v) {
			count += 1
		}
	}
	return count
}
